package com.zf.http_interface.caller.http_interface;

import com.zf.http_interface.caller.entity.UserInfo;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.service.annotation.GetExchange;
import org.springframework.web.service.annotation.HttpExchange;
import org.springframework.web.service.annotation.PostExchange;

import java.util.List;
import java.util.Map;

/**
 * Http Interface，服务 Controller 参见 {@link com.zf.http_interface.target.controller.BaseController}
 */
@HttpExchange(value = "/base")
public interface BaseHttpInterfaceService {
    /**
     * GET
     */
    @GetExchange("/hello")
    String hello(@RequestParam(name = "username", required = false) String username);

    /**
     * <pre>
     * RequestHeader 注解:
     *     1、注解Map参数时，使用Map中的 key, value 作为 请求头的名称和值
     *     2、注解String参数时，使用 @RequestHeader.name 属性的值作为请求头的名称，String参数的值作为请求头的值
     * </pre>
     */
    @GetExchange("/hello")
    String hello2(@RequestParam(name = "username", required = false) String username,
                  @RequestHeader(name = "hdMap") MultiValueMap<String, String> hdMap,
                  @RequestHeader(name = "oneHd") String oneHdxx);

    @GetExchange("/getUserInfo")
    UserInfo getUserInfo(@RequestParam(name = "username", required = false) String username,
                         @RequestParam(name = "age", required = false) Integer age);

    /**
     * <pre>
     * 注意：Http Interface 调用方式，不能直接使用实体类，实体类无法直接转换成 GET 参数：
     * 解决方式：
     * 1、使用 "Map类型+@RequestParam(name = "qp")" 可以正常转换成 GET 参数，必须要添加 @RequestParam 注解且指定name属性值（name可以是任意值，不能空）
     * 2、自定义 {@link org.springframework.web.service.invoker.HttpServiceArgumentResolver} 参数解析器，自行转换成 GET 参数
     * </pre>
     */
    @GetExchange("/getUserInfo")
    UserInfo getUserInfo2(@RequestParam(name = "qp") MultiValueMap<String, Object> userInfo);
    @GetExchange("/getUserInfo")
    UserInfo getUserInfo3(@RequestParam(name = "qp") Map<String, Object> userInfo);
    // UserInfo getUserInfo2(UserInfo userInfo);

    /**
     * <pre>
     * PathVariable: Feign支持参数后书写正则表达式，但是 Http Interface方式不支持，
     * 即 {username:[a-zA-Z]+} 中 “:” 后面的正则是不生效的，直接用 “username”作为参数
     * </pre>
     */
    @GetExchange("/getPathVar/{username:[a-zA-Z]+}/{age}")
    UserInfo getPathVar(@PathVariable(name = "username") String username,
                        @PathVariable(name = "age") Integer age);

    /**
     * Post Json, 加不加 contentType = MediaType.APPLICATION_JSON_VALUE 都可以
     */
    @PostExchange(value = "/addUserInfo")
    // @PostExchange(value = "/addUserInfo", contentType = MediaType.APPLICATION_JSON_VALUE)
    UserInfo addUserInfo(@RequestBody UserInfo userInfo);

    /**
     * <pre>
     * Http Interface方式发送 "multipart/form-data" 类型的表单请求，存在以下问题：
     * 1、表单文件 支持 {@link MultipartFile} 或 {@link Resource} 类型参数，且必须要 @RequestPart 注解标识。
     * 2、非文件部分，必须要用 @RequestParam 或者 @RequestPart 标明
     * 3、加不加 contentType = MediaType.MULTIPART_FORM_DATA_VALUE 都可以
     * 4、不支持直接使用实体类，除非自定义 {@link org.springframework.web.service.invoker.HttpServiceArgumentResolver} 参数解析器，自行转换
     */
    @PostExchange(value = "/uploadFile")
    // @PostExchange(value = "/uploadFile", contentType = MediaType.MULTIPART_FORM_DATA_VALUE)
    UserInfo uploadFile(@RequestParam("username") String username,
                        @RequestPart("age") Integer age,
                        @RequestPart("fileList") List<MultipartFile> fileList,
                        @RequestPart("fileList") List<Resource> fileList2);
    // UserInfo uploadFile2(FileUploadEntity fileUploadEntity);

    /**
     * ResponseEntity<byte[]>: 用来处理二进制内容，如文件
     */
    @GetExchange(value = "/downloadFile")
    ResponseEntity<byte[]> downloadFile();
}
